package com.dylan.magic.common.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;

/**
 * @author : ankang
 * @date : 2020/3/1 15:43
 * @Description :
 */
public class ThreadPoolUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolUtil.class);

    /** 执行异步任务的线程池，默认用cached thread pool */
    private static ThreadPoolExecutor executorService;
    private static final int DEFAULT_CORE_POOL_SIZE = 300;
    private static final int DEFAULT_MAX_POOL_SIZE = 300;
    /** second */
    private static final Long DEFAULT_KEEP_ALIVE_TIME = 60L;
    private static final int DEFAULT_TASK_QUEUE = 2000;
    /** 默认超时时间 */
    private static final int DEFAULT_TIMEOUT_MILLISECONDS = 1500;

    static {
        executorService = new ThreadPoolExecutor(DEFAULT_CORE_POOL_SIZE,
                DEFAULT_MAX_POOL_SIZE,
                DEFAULT_KEEP_ALIVE_TIME,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(DEFAULT_TASK_QUEUE),
                Executors.defaultThreadFactory());
    }

    public static ThreadPoolExecutor getExecutorService() {
        return executorService;
    }

    public static <T> Future<T> submitTask(Callable<T> callable){
        return executorService.submit(callable);
    }

    public static <T> Future<T> submitTaskCatchException(Callable<T> callable){
        return executorService.submit(() -> {
            try {
                return callable.call();
            } catch (Exception e) {
                LOGGER.error("异步调用异常", e);
            }
            return null;
        });
    }

    public static void executeTask(Runnable runnable) {
        executorService.execute(() -> {
            try {
                runnable.run();
            } catch (Exception e) {
                LOGGER.error("异步调用异常", e);
            }
        });
    }

    public static <T> T get(Future<T> future) {
        return get(future, "");
    }

    public static <T> T get(Future<T> future, long time) {
        return get(future, time, "");
    }


    public static <T> T get(Future<T> future, String logMessage) {
        if (future == null) {
            throw new IllegalArgumentException("获取异步任务结果，Future不能为null");
        }
        try {
            return future.get(DEFAULT_TIMEOUT_MILLISECONDS, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            LOGGER.error("ThreadPoolUtils error:" + logMessage, e);
        }
        return null;
    }

    public static <T> T get(Future<T> future, long time, String logMessage) {
        if (future == null) {
            throw new IllegalArgumentException("获取异步任务结果，Future不能为null");
        }
        try {
            return future.get(time, TimeUnit.MILLISECONDS);
        } catch (TimeoutException e) {
            LOGGER.error("ThreadPoolUtils timeout:" + logMessage, e);
        } catch (Exception e) {
            LOGGER.error("ThreadPoolUtils error:" + logMessage, e);
        }
        return null;
    }

    public static <T> T getWithException(Future<T> future) throws Exception {
        if (future == null) {
            throw new IllegalArgumentException("获取异步任务结果，Future不能为null");
        }
        try {
            return future.get(DEFAULT_TIMEOUT_MILLISECONDS, TimeUnit.MILLISECONDS);
        } catch (ExecutionException e) {
            throw getCauseException(e);
        }
    }

    public static <T> T getWithException(Future<T> future, long time) throws Exception {
        if (future == null) {
            throw new IllegalArgumentException("获取异步任务结果，Future不能为null");
        }
        try {
            return future.get(time, TimeUnit.MILLISECONDS);
        } catch (ExecutionException e) {
            throw getCauseException(e);
        }
    }

    private static Exception getCauseException(ExecutionException e) {
        if (e.getCause() instanceof Exception) {
            return (Exception) e.getCause();
        } else {
            return e;
        }
    }

}
